home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / zrgb.c < prev   
C/C++ Source or Header  |  1996-11-11  |  15KB  |  450 lines

  1. /*
  2.  * Copyright (c) 1993-94, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  21.  */
  22. /*
  23.  *   zrgb.c:  an openGL-Xlib RGB, zbuffer example program.
  24.  *
  25.  *              zrgb is the openGL "after" version of the IrisGL
  26.  *              "before" program, ~4Dgifts/examples/grafix/zrgb.c
  27.  *
  28.  *            - LEFTMOUSE:  move the 3 polygons around a center
  29.  *            - Esc key:  exit
  30.  * 
  31.  *    This program demostrates zbuffering 3 intersecting RGB polygons while
  32.  *  in doublebuffer mode where, movement of the mouse with the LEFTMOUSE
  33.  *  button depressed will, rotate the 3 polygons via compound rotations 
  34.  *  allowing continuous screen-oriented rotations.  (See orient(), and 
  35.  *  draw_scene() below).  Notice that there is no wasted CPU usage when the 
  36.  *  user moves the mouse out of the window without holding down LEFTMOUSE--
  37.  *  there is no "qtest" -type functionality being performed.  Hence the 
  38.  *  program simply blocks on the XNextEvent statement.
  39.  *
  40.  *                                   ratmandu -- ported to openGL, april 93
  41.  */
  42.  
  43. #include <GL/glx.h>
  44. #include <GL/glu.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <X11/keysym.h>
  48. #include <X11/Xlib.h>
  49. #include <X11/Xutil.h>
  50.  
  51. #define TRUE            1
  52. #define FALSE           0
  53.  
  54.  
  55. Display *dpy;                                    /* The X server connection */
  56. Atom del_atom;                                   /* WM_DELETE_WINDOW atom   */
  57. Window glwin;                                    /* handle to the GL window */
  58. XEvent event;
  59.  
  60. /* function declarations */
  61.  
  62. void openwindow(char *);
  63. void resize_buffer(void);
  64. void clean_exit(void);
  65. void initGL(void);
  66. void orient(void);
  67. void drawScene(void);
  68. void drawPolys(void);
  69.  
  70. static float objmat[16] = {
  71.          1.0, 0.0, 0.0, 0.0,
  72.          0.0, 1.0, 0.0, 0.0,
  73.          0.0, 0.0, 1.0, 0.0,
  74.          0.0, 0.0, 0.0, 1.0,
  75. };
  76.  
  77. int xsize, ysize;                        /* current size-of-window keepers */
  78. double scrnaspect;                                   /* aspect ratio value */
  79. int xpos, ypos, oxpos, oypos;                /* old and new mouse position */
  80.  
  81.  
  82.  
  83. main(argc,argv)
  84. int argc;
  85. char **argv;
  86. {
  87.     int myExpose, myConfigure, myButtPress, myKeyPress; 
  88.     int needToDraw = 0;                  /* don't set this to true until
  89.                                              we get our first Expose event */
  90.  
  91.  
  92.  
  93.     myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
  94.  
  95.     openwindow(argv[0]);
  96.    
  97.   
  98.    /* start out making the singlebuffer window be our current GL window */
  99.     initGL();                                          /* do GL init stuff */
  100.  
  101.     /*
  102.      * The event loop.
  103.      */
  104.     while (1) {         /* standard logic:  get event(s), process event(s) */
  105.  
  106.         XEvent event;
  107.         KeySym keysym;
  108.         char buf[4];
  109.  
  110.     /* this "do while" loop does the `get events' half of the "get events,
  111.      *  process events" action of the infinite while.  this is to ensure
  112.      *  the event queue is always drained before the events that have come
  113.      *  in are processed.
  114.      */
  115.         do {
  116.  
  117.             XNextEvent(dpy, &event);
  118.             switch (event.type) {
  119.  
  120.             /* "Expose" events are sort of like "REDRAW" in gl-speak in
  121.              *  terms of when a window becomes visible, or a previously
  122.              *  invisible part becomes visible.
  123.              */
  124.                 case Expose:                        /* Exposures */
  125.                     needToDraw = myExpose = TRUE;
  126.                     break;
  127.  
  128.             /* "ConfigNotify" events are like "REDRAW" in terms of changes
  129.              *   to a window's size or position.
  130.              */
  131.                 case ConfigureNotify:                /* Resize GL manually */
  132.                     xsize = event.xconfigure.width;
  133.                     ysize = event.xconfigure.height;
  134.                     needToDraw = myConfigure = TRUE;
  135.                     break;
  136.  
  137.             /* Wait for "MotionNotify" events so the queue doesn't fill up
  138.              */
  139.                 case MotionNotify:                        
  140.                     myButtPress = TRUE;
  141.                     xpos = event.xmotion.x;
  142.                     ypos = event.xmotion.y;
  143.                     break;
  144.  
  145.             /* "ClientMessage" is generated if the WM itself is being
  146.              *  gunned down and sends an exit signal to any running prog.
  147.              */
  148.                 case ClientMessage:
  149.                     if (event.xclient.data.l[0] == del_atom)
  150.                         clean_exit();
  151.                     break;
  152.  
  153.             /* "KeyPress" events are those that would be generated before
  154.              *   whenever queueing up any KEYBD key via qdevice.
  155.              */
  156.                 case KeyPress:
  157.                    /* save out which unmodified key (i.e. the  key was
  158.                     *  not modified w/something like "Shift", "Ctrl",
  159.                     *  or "Alt") got pressed for use below.
  160.                     */
  161.                     XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
  162.                     myKeyPress = TRUE;
  163.                     break;
  164.  
  165.               }  /* end switch (event.type) */
  166.  
  167.  
  168.         } while (XPending(dpy));   /* end "do { } while".
  169.                                     * XPending() is like qtest()--it only
  170.                                     * tells you if there're any events
  171.                                     * presently in the queue.  it does not
  172.                                     * disturb queue's contents in any way.
  173.                                     */
  174.  
  175.     /* On an "Expose" event, redraw the affected pop'd or de-iconized window
  176.      */
  177.         if (myExpose) {
  178.             resize_buffer();   
  179.             myExpose = FALSE;               /* reset flag--queue now empty */
  180.         }
  181.  
  182.     /* On a "ConfigureNotify" event, the GL window has either been moved or
  183.      *  resized.  Respond accordingly and then redraw its contents.
  184.      */
  185.         if (myConfigure) {
  186.             oxpos = xpos;
  187.             oypos = ypos;
  188.             resize_buffer();   
  189.             myConfigure = FALSE;            /* reset flag--queue now empty */
  190.         }
  191.  
  192.         if (needToDraw) {
  193.             drawScene();
  194.             needToDraw = FALSE;
  195.         }
  196.  
  197.         /* On a keypress of Esc key, exit program.
  198.          */
  199.         if (myKeyPress) {
  200.             if (keysym == XK_Escape)
  201.                 clean_exit();
  202.         }
  203.  
  204.         if (myButtPress) {
  205.             orient();
  206.             drawScene();
  207.             myButtPress = FALSE;
  208.         }
  209.     }      /* end while(1) */
  210.  
  211. }      /* end main */
  212.  
  213.  
  214.  
  215. static int attributeList[] = { GLX_RGBA, 
  216.                                GLX_DOUBLEBUFFER, 
  217.                                GLX_RED_SIZE, 1, 
  218.                                GLX_GREEN_SIZE, 1, 
  219.                                GLX_BLUE_SIZE, 1,
  220.                    GLX_DEPTH_SIZE, 1,
  221.                                None };
  222. static int attributeList2[] = { GLX_RGBA,
  223.                                GLX_RED_SIZE, 1,
  224.                                GLX_GREEN_SIZE, 1,
  225.                                GLX_BLUE_SIZE, 1,
  226.                                GLX_DEPTH_SIZE, 1,
  227.                                None };
  228.  
  229.  
  230. static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
  231.     return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
  232. }
  233.  
  234. XSizeHints Winhints;                          /* used to fix window size */
  235.  
  236.  
  237. /*  openwindow -
  238.  *     establish connection to X server, get screen info, specify the
  239.  *     attributes we want the WM to try to provide, and create the GL window
  240.  */
  241. void openwindow(char *progname) {
  242.  
  243.     XVisualInfo *vi;
  244.     GLXContext cx;
  245.     Colormap cmap;
  246.     XSizeHints Winhints;                          /* used to fix window size */
  247.     XSetWindowAttributes swa;
  248.     int scrnnum;                               /* X screen number            */
  249.     int xorig, yorig;                          /* window (upper-left) origin */
  250.     long scrnheight;
  251.  
  252.  
  253.  
  254.  
  255.    /* define window initial size */
  256.     xorig = 50;  yorig = 40;
  257.     xsize = 300; ysize = 240;
  258.     scrnaspect = xsize / (double) ysize;
  259.  
  260.    /* Connect to the X server and get screen info */
  261.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  262.         fprintf(stderr, "%s: cannot connect to X server %s\n",
  263.                                  progname, XDisplayName(NULL));
  264.         exit(1);
  265.     }
  266.  
  267.     scrnnum = DefaultScreen(dpy);
  268.     scrnheight = DisplayHeight(dpy, scrnnum);
  269.  
  270.         /* get an appropriate visual */
  271.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
  272.     if (vi == NULL) {
  273.         fprintf(stderr, "Unable to obtain Doublebuffered visual;  ");
  274.         fprintf(stderr, "now going for singlebuffer'd...\n");
  275.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
  276.     }
  277.     if (vi == NULL) {
  278.         printf("Unable to obtain Singlebuffered VISUAL(????)\n");
  279.         exit(0);
  280.     }
  281.  
  282.     /* create a GLX context */
  283.     cx = glXCreateContext(dpy, vi, None, GL_TRUE);
  284.  
  285.     /* create a colormap */
  286.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  287.                            vi->visual, AllocNone);
  288.  
  289.     /* create a window */
  290.     swa.colormap = cmap;
  291.     swa.border_pixel = 0;
  292.     swa.event_mask = StructureNotifyMask  | ButtonPressMask | ExposureMask |
  293.          Button1MotionMask | KeyPressMask;    /* express interest in events */;
  294.     glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  295.                           xorig, yorig, xsize, ysize, 
  296.                           0, vi->depth, InputOutput, vi->visual,
  297.                           CWBorderPixel|CWColormap|CWEventMask, &swa);
  298.  
  299.     XMapWindow(dpy, glwin);
  300.     XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
  301.  
  302.     /* connect the context to the window */
  303.     glXMakeCurrent(dpy, glwin, cx);
  304.  
  305.     if (!(glwin)) {
  306.         fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
  307.         exit(1);
  308.     }
  309.  
  310.    /* define string that will show up in the window title bar (and icon) */
  311.     XStoreName(dpy, glwin, "z-buffered rgb program");
  312.  
  313.    /* specify the values for the Window Size Hints we want to enforce:  this
  314.     *  window's aspect ratio needs to stay at 1:1, constrain min and max
  315.     *  window size, and specify the initial size of the window.
  316.     */
  317.     Winhints.width  = xsize;          /* specify desired x/y size of window */
  318.     Winhints.height = ysize;
  319.     Winhints.min_width = xorig;                       /* define min and max */
  320.     Winhints.max_width = scrnheight-1;                /* width and height   */
  321.     Winhints.min_height = yorig;
  322.     Winhints.max_height = scrnheight-1;
  323.     Winhints.min_aspect.x = xsize;    /* keep aspect to a xsize:ysize ratio */
  324.     Winhints.max_aspect.x = xsize;
  325.     Winhints.min_aspect.y = ysize;
  326.     Winhints.max_aspect.y = ysize;
  327.     Winhints.flags = USSize|PMaxSize|PMinSize|PAspect;           /* set the */
  328.     XSetNormalHints(dpy, glwin, &Winhints);      /* corresponding flags */
  329.  
  330.    /* express interest in WM killing this app */
  331.     if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
  332.         XSetWMProtocols(dpy, glwin, &del_atom, 1);
  333.  
  334.     return ;
  335. }
  336.  
  337.  
  338.  
  339.  
  340. /*  window has been moved or resized so update viewport & CTM stuff.
  341.  */
  342. void resize_buffer() {
  343.  
  344.     XSync(dpy, False);  /* STILL NEED THIS????? *//* Need before GL reshape */
  345.     scrnaspect = xsize / (double) ysize;
  346.     glViewport(0, 0, xsize-1, ysize-1);
  347. }
  348.  
  349.  
  350.  
  351. /*  clean up before exiting
  352.  */
  353. void clean_exit(void)
  354. {
  355.     XCloseDisplay(dpy);
  356.     exit(0);
  357. }
  358.  
  359.  
  360.  
  361. /* setup all necessary GL initialzation parameters.
  362.  */
  363. void initGL()
  364. {
  365.     glEnable(GL_DEPTH_TEST);
  366.     glClearColor(0.16, 0.39, 0.78, 0.0);
  367.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  368.     glLoadIdentity();
  369.     gluPerspective(400.0, scrnaspect, 30.0, 1000.0);
  370. }
  371.  
  372.  
  373. void orient() 
  374. {
  375.     float dx, dy;
  376.  
  377.     glPushMatrix();
  378.     dx = xpos-oxpos;
  379.     dy = oypos-ypos;
  380.     glLoadIdentity();
  381.     glRotatef((float) (0.03*(xpos-oxpos)), 1.0, 0.0, 0.0);
  382.     glRotatef((float) (0.03*(oypos-ypos)), 0.0, 1.0, 0.0);
  383.     glMultMatrixf(objmat);
  384.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  385.  
  386.     glPopMatrix();
  387. }
  388.  
  389.  
  390. void drawScene() 
  391. {
  392.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  393.  
  394.     glPushMatrix();
  395.     glTranslatef(0.0, 0.0, -40.0);
  396.     glMultMatrixf(objmat);
  397.     glRotatef(-220.0, 0.0, 1.0, 0.0);  /* skews orig view to show all polys */
  398.     drawPolys();
  399.     glPopMatrix();
  400.     glFlush ();
  401.     glXSwapBuffers(dpy, glwin);
  402. }
  403.  
  404.  
  405. float polygon1[3][3] = { {-10.0, -10.0,   0.0,},
  406.                          { 10.0, -10.0,   0.0,},
  407.                          {-10.0,  10.0,   0.0,} };
  408.  
  409. float polygon2[3][3] = { {  0.0, -10.0, -10.0,},
  410.                          {  0.0, -10.0,  10.0,},
  411.                          {  0.0,   5.0, -10.0,} };
  412.  
  413. float polygon3[4][3] = { {-10.0,   6.0,   4.0,},
  414.                          {-10.0,   3.0,   4.0,},
  415.                          {  4.0,  -9.0, -10.0,},
  416.                          {  4.0,  -6.0, -10.0,} };
  417.  
  418. void drawPolys() 
  419. {
  420.     glBegin(GL_POLYGON);
  421.     glColor4f(0.0, 0.0, 0.0, 0.0);
  422.     glVertex3fv(&polygon1[0][0]);
  423.     glColor4f(0.5, 0.5, 0.5, 0.0);
  424.     glVertex3fv(&polygon1[1][0]);
  425.     glColor4f(1.0, 1.0, 1.0, 0.0);
  426.     glVertex3fv(&polygon1[2][0]);
  427.     glEnd();
  428.  
  429.     glBegin(GL_POLYGON);
  430.     glColor4f(1.0, 1.0, 0.0, 0.0);
  431.     glVertex3fv(&polygon2[0][0]);
  432.     glColor4f(0.0, 1.0, 0.5, 0.0);
  433.     glVertex3fv(&polygon2[1][0]);
  434.     glColor4f(0.0, 0.0, 1.0, 0.0);
  435.     glVertex3fv(&polygon2[2][0]);
  436.     glEnd();
  437.  
  438.     glBegin(GL_POLYGON);
  439.     glColor4f(1.0, 1.0, 0.0, 0.0);
  440.     glVertex3fv(&polygon3[0][0]);
  441.     glColor4f(1.0, 0.0, 1.0, 0.0);
  442.     glVertex3fv(&polygon3[1][0]);
  443.     glColor4f(0.0, 0.0, 1.0, 0.0);
  444.     glVertex3fv(&polygon3[2][0]);
  445.     glColor4f(1.0, 0.0, 1.0, 0.0);
  446.     glVertex3fv(&polygon3[3][0]);
  447.     glEnd();
  448.  
  449. }
  450.